﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IURIP;
using System.Xml;
using URIP.Tool;

namespace URIP.Core
{
    public class MapItem : IMapItem
    {
        public MapItem(IMap map, IMapItem parent)
        {
            m_map = map;
            m_parent = parent;
        }

        private IMap m_map = null;
        private bool m_isList = false;
        private string m_name = "";
        private string m_dataBlockName = "";
        private string m_sourceXPath = "";
        private IMapItem m_parent = null;
        private List<IMapItem> m_children = new List<IMapItem>();
        private Dictionary<string, IMapItem> m_childrenDic = new Dictionary<string, IMapItem>();
        private Dictionary<string, List<IMapItem>> m_childrenGroup = new Dictionary<string, List<IMapItem>>();

        public ITask Task
        {
            get { return m_map.Task; }
        }
        public ITarget Target
        {
            get { return m_map.Target; }
        }
        public IMap Map
        {
            get { return m_map; }
        }
        public bool IsList
        {
            get { return m_isList; }
        }
        public string Name
        {
            get { return m_name; }
        }
        public string DataBlockName
        {
            get { return m_dataBlockName; }
        }
        public string SourceXPath
        {
            get { return m_sourceXPath; }
        }
        public IMapItem Parent
        {
            get { return m_parent; }
        }
        public List<IMapItem> Children
        {
            get { return m_children; }
        }

        public void InitByConfiguration(XmlNode node)
        {
            if (node.Name == "field" || node.Name == "list")
            {
                this.m_name = Util.GetAttributeValue(node, "name", true);
                if (string.IsNullOrEmpty(this.m_name))
                {
                    throw new Exception(string.Format("There is a map item has no valid name attribute for target '{0}'. All map items should have unique name.", Target.Name));
                }
                this.m_isList = node.Name == "list";
                this.m_dataBlockName = Util.GetAttributeValue(node, "dataBlock", true);
                this.m_sourceXPath = Util.GetAttributeValue(node, "sourceXPath", true);
                if (!Target.DataBlocks.ContainsKey(this.m_dataBlockName))
                {
                    Task.Logger.LogWarning("The data block {0} does not exist, it will be replaced with empty in map", this.m_dataBlockName);
                    this.m_dataBlockName = "";
                }
                if (this.m_dataBlockName != "" && !Map.DataBlocks.Contains(this.m_dataBlockName))
                {
                    Map.DataBlocks.Add(this.m_dataBlockName);
                }

                if (this.m_isList)
                {
                    XmlNodeList childrenList = node.SelectNodes("./listItem/*");
                    for (int i = 0; i < childrenList.Count; i++)
                    {
                        MapItem item = new MapItem(m_map, this);
                        item.InitByConfiguration(childrenList[i]);
                        if (m_childrenDic.ContainsKey(item.Name))
                        {
                            throw new Exception(string.Format("The DataMap item name '{0}' for target '{1}' is repeated, it should be renamed", this.GetFullPath("", item), Target.Name));
                        }
                        else
                        {
                            m_children.Add(item);
                            m_childrenDic.Add(item.Name, item);
                            if (!m_childrenGroup.ContainsKey(item.DataBlockName))
                            {
                                m_childrenGroup[item.DataBlockName] = new List<IMapItem>();
                            }
                            m_childrenGroup[item.DataBlockName].Add(item);
                        }
                    }
                }
            }
        }
        public IMapItem GetMapItemByName(string name)
        {
            if (m_childrenDic.ContainsKey(name))
            {
                return m_childrenDic[name];
            }
            return null;
        }
        public List<IMapItem> GetListByBlockName(string blockName)
        {
            if (m_childrenGroup.ContainsKey(blockName))
            {
                return m_childrenGroup[blockName];
            }
            return new List<IMapItem>();
        }

        private string GetFullPath(string name, IMapItem item)
        {
            name = item.Name + "/" + name;
            if (item.Parent != null)
            {
                return GetFullPath(name, item.Parent);
            }
            else
            {
                return name.TrimEnd('/');
            }
        }
    }
}
